package com.erdos.common.web.tag;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.erdos.common.pagination.Page;
import com.erdos.common.service.AppServiceHelper;


public class PageTag extends BodyTagSupport {

	private static final long serialVersionUID = -2756529597196138810L;

	private static final Log logger = LogFactory.getLog(PageTag.class);

	/** 页面跳转链接显示个数 */
	private static int MAX_SHOW_NUMBER = 6; // summation of preList + floList

	/** 下拉框列表 */
	private static String INIT_PAGE_SIZE_LIST = "10,20,50,100,200";

	/** 每页显示下拉框项目列表 */
	private String pageSizeList = null;

	/**
	 * @param pageSizeList
	 *            要设置的 pageSizeList。
	 */
	public void setPageSizeList(String pageSizeList) {
		this.pageSizeList = pageSizeList;
	}

	/** AJAX操作的目标DIV名称 */
	private String targets;

	public void setTargets(String targets) {
		this.targets = targets;
	}

	/**
	 * 标签核心方法
	 */
	public int doStartTag() throws JspException {
		// 获取request
		HttpServletRequest request = (HttpServletRequest) pageContext
				.getRequest();
		Page page = (Page) request.getAttribute("page");

		// 从request中获取需要的值，前提要求Action方法中必须在request中设置相应的属性值
		int pageNo = page.getPageNo();
		int limit = page.getLimit();
		int totalPages = page.getTotalPages();

		JspWriter out = pageContext.getOut();

		try {
			out
					.print("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">	<tr><td class=\"compactToolbar\" align=\"left\">");
			printOutFront(pageNo, request);
			buildPager(request, pageNo, totalPages);
			printOutBack(pageNo, totalPages, request);
			buildGoto(request,pageNo,totalPages);
			//buildRefresh(request,pageNo);
			printOutEnd();
			out.print("</td><td></td><td class=\"statusBar\" align=\"right\">");
			buildSelecter(request, limit);
			
			int pn=0;
			if(pageNo>0&&totalPages>0){
				pn=pageNo;
			}
			
			int start=0;
			if(pageNo>0&&totalPages>0){
				start=page.getOffset() + 1;
			}
			
			out.print("第" + pn + "页/共"	+ page.getTotalPages()+"页("+ start + "-"+ page.getEndIndex() + " of " +page.getTotalRows()+")");

			out.print("</td></tr></table>");
			out.print("<script type=\"text/javascript\">");
			String pageURL=(String)request.getAttribute("pageURL");
			out.print("dojo.widget.byId(\"" + targets + "\").href = '" + pageURL +"';");
			out.print("</script>");
		} catch (IOException e) {
			e.printStackTrace();
		}

		return EVAL_PAGE;
	}
	
	/**
	 * build up goto text area and print
	 * 
	 * @throws JspException
	 */
	private void buildGoto(HttpServletRequest request, int pageNo,int totalPages)
			throws JspException {
		try {
			JspWriter out = pageContext.getOut();
			if (StringUtils.isEmpty(pageSizeList)) {
				pageSizeList = INIT_PAGE_SIZE_LIST;
			}
			String[] pageSizes = pageSizeList.split(",");
			String rand=UUID.randomUUID().toString();
			String outString = "<td><input name=\"gotoText"+rand+"\" type=\"text\" class=\"textinput\" size=\"5\"  value=\""+pageNo+"\" onkeydown=\"return gotoPage(this.value,'"+pageNo+"','"+totalPages+"','"+targets+"');\">"+"<input type=\"button\" name=\"go\" value=\"GO\" class=\"button2\" onclick=\"return gotoPageDirect($('gotoText"+rand+"').value,'"+pageNo+"','"+totalPages+"','"+targets+"');\"></td>";
			out.print(outString);
		} catch (Exception e) {
			throw new JspException(e);
		}
	}

	/**
	 * build up selecter and print
	 * 
	 * @throws JspException
	 */
	private void buildSelecter(HttpServletRequest request, int limit)
			throws JspException {
		try {
			JspWriter out = pageContext.getOut();
			if (StringUtils.isEmpty(pageSizeList)) {
				pageSizeList = INIT_PAGE_SIZE_LIST;
			}
			String[] pageSizes = pageSizeList.split(",");
			String outString = "每页<select name=\"pageSizeSelect\" onchange=\"setLimit(this.value,'"+targets+"')\">";
			for (int i = 0; i < pageSizes.length; i++) {
				if (limit==Integer.parseInt(pageSizes[i])) {
					outString += "<option selected  value=\"" + pageSizes[i]
							+ "\">" + pageSizes[i] + "</option>";
				} else {
					outString += "<option value=\"" + pageSizes[i] + "\">"
							+ pageSizes[i] + "</option>";
				}
			}
			outString += "</select>";
			out.print(outString);
		} catch (Exception e) {
			throw new JspException(e);
		}
	}

	private void buildRefresh(HttpServletRequest request,int pageNo) throws JspException {
		try {
			JspWriter out = pageContext.getOut();
			StringBuffer outString = new StringBuffer(50);
			outString.append("<td>");
			outString.append("<a href=\"javascript:setPage('"+ pageNo +"','"+targets+"');\">");
			outString.append("<img src='" + request.getContextPath()
					+ "/images/table/refresh.gif\' style='border:0' />");
			outString.append("</a></td>");
			out.print(outString.toString());
		} catch (Exception e) {
			throw new JspException(e);
		}
	}

	/**
	 * build jsp page and print out
	 * 
	 * @param pageNo
	 * @param totalPage
	 * @throws JspException
	 */
	private void buildPager(HttpServletRequest request, int pageNo,
			int totalPages) throws JspException {

		logger.debug("pageNo=" + pageNo);
		logger.debug("totalPages=" + totalPages);

		Map map = getPreFloList(pageNo, totalPages);
		List preList = (List) map.get("preList");
		List floList = (List) map.get("floList");

		// logger.debug("preList.size()=" + preList.size());
		// logger.debug("floList.size()=" + floList.size());

		if (preList != null && preList.size() > 0) {
			for (int i = 0; i < preList.size(); i++) {
				printOutPages(request, "pre", (String) preList.get(i));
			}
		}
		printOutPages(request, "now", String.valueOf(pageNo));
		if (floList != null && floList.size() > 0) {
			for (int i = 0; i < floList.size(); i++) {
				printOutPages(request, "pre", (String) floList.get(i));
			}
		}

	}

	/**
	 * get pre and flo list
	 * 
	 * @param pageNo
	 * @param totalPages
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Map getPreFloList(int pageNo, int totalPages) {
		int maxShow = MAX_SHOW_NUMBER; // summation of preList + floList sizes
		List preList = new ArrayList();
		List floList = new ArrayList();
		List bakPreList = new ArrayList();
		List bakFloList = new ArrayList();
		int i = 0;
		for (int j = pageNo - 1; j > 0 && i < maxShow; j--, i++) {
			bakPreList.add(String.valueOf(j));
		}
		i = 0;
		for (int j = pageNo + 1; j <= totalPages && i < maxShow; j++, i++) {
			bakFloList.add(String.valueOf(j));
		}
		int preLength;
		int floLength;
		if (bakPreList.size() >= maxShow / 2) {
			if (bakFloList.size() >= maxShow / 2) {
				preLength = maxShow / 2;
				floLength = maxShow / 2;
			} else {
				floLength = bakFloList.size();
				if (bakPreList.size() >= (maxShow - floLength)) {
					preLength = maxShow - floLength;
				} else {
					preLength = bakPreList.size();
				}
			}
		} else {
			if (bakFloList.size() >= maxShow / 2) {
				preLength = bakPreList.size();
				if (bakFloList.size() >= (maxShow - preLength)) {
					floLength = maxShow - preLength;
				} else {
					floLength = bakFloList.size();
				}
			} else {
				preLength = bakPreList.size();
				floLength = bakFloList.size();
			}
		}
		for (int j = 0; j < floLength; j++) {
			floList.add(bakFloList.get(j).toString());
		}
		for (int j = preLength - 1; j >= 0; j--) {
			preList.add(bakPreList.get(j).toString());
		}
		Map map = new HashMap();
		map.put("preList", preList);
		map.put("floList", floList);
		return map;

	}

	/**
	 * print info to jsp page
	 * 
	 * @param mothod
	 * @param page
	 * @throws JspException
	 */
	private void printOutPages(HttpServletRequest request, String mothod,
			String page) throws JspException {
		if (mothod.endsWith("now")) {
			try {
				JspWriter out = pageContext.getOut();
				String outString = "&nbsp;<span><font class='currentNum'>["
						+ page + "]</font></span>";
				out.print(outString);
			} catch (Exception e) {
				throw new JspException(e);
			}
		} else {
			try {
				JspWriter out = pageContext.getOut();
				String outString = "&nbsp;" + "<a href=\"javascript:setPage('"
						+ page + "','" + targets + "');\">"
						+ "<span class='clsResGridViewPaging'>" + page + "</span></a>";
				out.print(outString);
			} catch (Exception e) {
				throw new JspException(e);
			}
		}
	}

	/**
	 * 组装标签前部分
	 * 
	 * @param pageNo
	 * @param request
	 * @throws JspException
	 */
	private void printOutFront(int pageNo, HttpServletRequest request)
			throws JspException {
		try {
			String first = AppServiceHelper.getMessage("prompt.page.first",
					null, request.getLocale());
			String prev = AppServiceHelper.getMessage("prompt.page.prev", null,
					request.getLocale());
			JspWriter out = pageContext.getOut();
			String outString = "";
			if (pageNo == 1) {
				outString = "<table border=\"0\" cellpadding=\"1\" cellspacing=\"2\">"
						+ "	<tr>"
						+ " <td><span class='clsResGridViewPagingDisabled'>"
						+ first
						+ "</span>&nbsp;</td>"
						+ " <td><span class='clsResGridViewPagingDisabled'>"
						+ prev + "</span>&nbsp;</td>" + " <td>";
			} else {
				Integer prePage = new Integer(pageNo == 1 ? pageNo : pageNo - 1);
				outString = "<table border=\"0\" cellpadding=\"1\" cellspacing=\"2\">"
						+ "	<tr>"
						+ " <td>"
						+ "<a href=\"javascript:setPage('"
						+ 1
						+ "','"
						+ targets
						+ "');\"><span class='clsResGridViewPaging'>"
						+ first
						+ "</span>&nbsp;</a></td>"
						+ " <td>"
						+ "<a href=\"javascript:setPage('"
						+ prePage
						+ "','"
						+ targets
						+ "');\"><span class='clsResGridViewPaging'>"
						+ prev + "</span>&nbsp;</a></td>" + " <td>";
			}
			out.print(outString);
		} catch (Exception e) {
			throw new JspException(e);
		}

	}

	/**
	 * 组装标签后部分
	 * 
	 * @param pageNo
	 * @param totalPage
	 * @param request
	 * @throws JspException
	 */
	private void printOutBack(int pageNo, int totalPages,
			HttpServletRequest request) throws JspException {
		try {
			//logger.debug("totalPages="+totalPages);
			Integer nextPage = new Integer(pageNo == totalPages ? totalPages
					: pageNo + 1);
			String next = AppServiceHelper.getMessage("prompt.page.next", null,
					request.getLocale());
			String last = AppServiceHelper.getMessage("prompt.page.last", null,
					request.getLocale());
			JspWriter out = pageContext.getOut();
			String outString = "";
			if (pageNo == totalPages||totalPages==0||totalPages==1) {
				outString = " </td>"
						+ " <td><span class='clsResGridViewPagingDisabled'>"
						+ next
						+ "</span>&nbsp;</td>"
						+ " <td><span class='clsResGridViewPagingDisabled'>"
						+ last
						+ "</span>&nbsp;</td>";
			} else {
				outString = " </td>" + " <td>"
						+ "<a href=\"javascript:setPage('"
						+ nextPage
						+ "','"
						+ targets
						+ "');\"><span class='clsResGridViewPaging'>"
						+ next
						+ "</span>&nbsp;</a></td>"
						+ " <td>"
						+ "<a href=\"javascript:setPage('"
						+ totalPages
						+ "','"
						+ targets
						+ "');\"><span class='clsResGridViewPaging'>"
						+ last
						+ "</span>&nbsp;</a></td>";
			}
			out.print(outString);
		} catch (Exception e) {
			throw new JspException(e);
		}
	}

	/**
	 * 组装标签结束标记
	 * 
	 * @throws JspException
	 */
	private void printOutEnd() throws JspException {
		try {
			JspWriter out = pageContext.getOut();
			String outString = " </tr></table>";
			out.print(outString);
		} catch (Exception e) {
			throw new JspException(e);
		}
	}
}
